package com.lenovo.lcdm.team.common.token;

import cn.hutool.core.date.DateUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.google.common.base.Throwables;
import com.lenovo.lcdm.common.exception.InvalidTokenException;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @author
 * @date
 **/
@Slf4j
public class TokenSupport {

    public static final String TOKEN_HEADER_KEY = "Authorization-JWT";

    /**
     * 密钥
     */
    public static final String SECRET_KEY = "com.lenovo.plm.LOIS-service";
    /**
     * token过期时间 1天
     */
    public static final long TOKEN_EXPIRE_TIME = TimeUnit.HOURS.toMillis(12L);
    /**
     * 签发人
     */
    private static final String ISSUER = "LOIS-ADMIN";
    /**
     * JWT Key  IT Code
     */
    public static final String JWT_KEY_IT_CODE = "IT_CODE";

    private static Algorithm getAlgorithm() {
        return Algorithm.HMAC256(SECRET_KEY);
    }

    /**
     * 生成签名
     */
    public static String generateToken(String itCode) {
        return JWT.create()
                //签发人
                .withIssuer(ISSUER)
                //签发时间
                .withIssuedAt(new Date())
                //过期时间
                .withExpiresAt(new Date(System.currentTimeMillis() + TOKEN_EXPIRE_TIME))
                //用户id
                .withClaim(JWT_KEY_IT_CODE, itCode)
                // 签名
                .sign(getAlgorithm());
    }

    /**
     * 验证token
     */
    public static boolean verify(String token) {
        try {
            //算法
            JWTVerifier verifier = JWT.require(getAlgorithm())
                    .acceptExpiresAt(0L)
                    .withIssuer(ISSUER)
                    .build();
            verifier.verify(token);
            return true;
        } catch (Exception ex) {
            log.info("TokenSupport verify failed, token:{}, ex:{}", token, Throwables.getStackTraceAsString(ex));
            throw new InvalidTokenException();
        }
    }

    public static Claim getItCode(String token) {
        return getClaim(token, JWT_KEY_IT_CODE);
    }

    /**
     * 获得Token中的信息无需secret解密也能获得
     *
     * @param token
     * @param claim
     * @return
     */
    public static Claim getClaim(String token, String claim) {
        verify(token);
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim(claim);
        } catch (JWTDecodeException ex) {
            log.info("TokenUtil getClaim failed, token:{}, ex:{}", token, Throwables.getStackTraceAsString(ex));
            throw new InvalidTokenException();
        }
    }


    /**
     * 判断token 时间是否有效
     */
    public static boolean judgeDate(String token) {

        try {
            DecodedJWT jwt = JWT.decode(token);
            Date date = jwt.getExpiresAt();
            int i = DateUtil.compare(date, new Date());

            return i >= 0;
        } catch (JWTDecodeException e) {
            return false;
        }
    }
}
